package cn.doveshelly.teslamate.task;


import cn.doveshelly.teslamate.data.Gps;
import cn.doveshelly.teslamate.mapper.DrivesMapper;
import cn.doveshelly.teslamate.mapper.GpsMapper;
import cn.doveshelly.teslamate.utils.CommonConfig;
import cn.doveshelly.teslamate.utils.CommonUtils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 校正位置信息
 */
@Component
@Slf4j
public class PositionTask {

    @Autowired
    private GpsMapper gpsMapper;

    @Autowired
    private CommonUtils commonUtils;

    @Autowired
    private CommonConfig commonConfig;

    @Value("${alert.enabled}")
    public boolean enabled;

    // 百度地图API限流控制 - 最后一次调用时间
    private static final AtomicLong lastApiCallTime = new AtomicLong(0);
    // API调用间隔（毫秒），假设TPS=1，即每秒最多1次调用
    private static final long API_CALL_INTERVAL_MS = 200;

    /**
     * 校正坐标信息
     */
    @Scheduled(fixedDelay = 60000)
    public void fixPosition() {
        List<Gps> gpsList = gpsMapper.selectList(Wrappers.<Gps>lambdaQuery().eq(Gps::getAddress, "未知位置"));

        if (CollUtil.isEmpty(gpsList)) {
            return;
        }
        for (Gps gps : gpsList) {
            updateAddress(gps);
        }
    }

    private void updateAddress(Gps gps) {
        String name = null;
        String latitude = gps.getLatitude();
        String longitude = gps.getLongitude();
        try {
            // API限流控制
            rateLimitApiCall();

            // 构建百度地图逆地理编码API请求URL
            String url = "http://api.map.baidu.com/reverse_geocoding/v3/?ak={}&output=json&coordtype=wgs84ll&location={},{}&extensions_poi=1&radius=100";
            String json = HttpUtil.get(StrUtil.format(url, commonConfig.getBaiduKey(), latitude, longitude));
            log.info("百度地图API响应: {}", json);

            if (StrUtil.isBlank(json)) {
                log.warn("百度地图API返回空响应，坐标: ({}, {})", latitude, longitude);
                // name = "未知位置";
            } else {
                JSONObject jsonObject = JSONUtil.parseObj(json);

                // 检查API响应状态
                Integer status = jsonObject.getInt("status");
                if (status == null || status != 0) {
                    log.warn("百度地图API返回错误状态: {}, 坐标: ({}, {})", status, latitude, longitude);
                    // name = "未知位置";
                } else {
                    JSONObject result = jsonObject.getJSONObject("result");
                    if (result != null && result.containsKey("formatted_address")) {
                        name = result.get("formatted_address", String.class);
                        if (StrUtil.isBlank(name)) {
                            name = "未知位置";
                        }
                    } else {
                        log.warn("百度地图API未返回POI信息，坐标: ({}, {})", latitude, longitude);
                        name = "未知位置";
                    }
                }
            }
        } catch (Exception e) {
            log.error("调用百度地图API获取地址失败，坐标: ({}, {})", latitude, longitude, e);
            name = "未知位置";
        }

        // 将查询结果缓存到数据库
        try {

            gps.setAddress(name);
            gpsMapper.updateById(gps);
            log.debug("地址信息已更新到数据库: {} -> {}", latitude + "," + longitude, name);
        } catch (Exception e) {
            log.error("更新地址信息到数据库失败，坐标: ({}, {}), 地址: {}", latitude, longitude, name, e);
            // 数据库保存失败不影响返回结果
        }
    }

    /**
     * API限流控制方法
     * 确保两次API调用之间有足够的时间间隔
     */
    private void rateLimitApiCall() {
        long currentTime = System.currentTimeMillis();
        long lastCallTime = lastApiCallTime.get();
        long timeSinceLastCall = currentTime - lastCallTime;

        if (timeSinceLastCall < API_CALL_INTERVAL_MS) {
            long sleepTime = API_CALL_INTERVAL_MS - timeSinceLastCall;
            try {
                log.debug("API限流控制：等待 {} 毫秒后调用", sleepTime);
                Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                log.warn("API限流等待被中断", e);
            }
        }

        // 更新最后调用时间
        lastApiCallTime.set(System.currentTimeMillis());
    }
}
